"""
Main CLI entry point for CodeMCP.

Provides command-line interface for analyzing function call trees,
interactive exploration, and configuration management.
"""

import argparse
import asyncio
import sys
import json
from typing import Dict, Any, Optional, List
from pathlib import Path
import signal
import os

from ..core.config import Config, load_config
from ..core.error_handler import handle_error, log_info, log_warning, CodeMCPError
from .commands.analyze import AnalyzeCommand
from .commands.explore import ExploreCommand
from .commands.config import ConfigCommand
from .commands.session import SessionCommand
from .commands.discover import DiscoverCommand
from .commands.classify import ClassifyCommand
from .commands.resolve import ResolveCommand
from .utils.formatter import OutputFormatter, OutputFormat
from .utils.colors import ColorPrinter
from .utils.progress import ProgressIndicator


class CodeMCPCLI:
    """Main CLI application class."""
    
    def __init__(self, config: Config = None):
        self.config = config or Config()
        self.formatter = OutputFormatter()
        self.printer = ColorPrinter()
        self.progress = ProgressIndicator()
        self.session_data = {}
        self.is_running = True
        
        # Initialize commands
        self.commands = {
            'analyze': AnalyzeCommand(self),
            'explore': ExploreCommand(self), 
            'config': ConfigCommand(self),
            'session': SessionCommand(self),
            'discover': DiscoverCommand(self),
            'classify': ClassifyCommand(self),
            'resolve': ResolveCommand(self)
        }
        
        # Setup signal handlers
        signal.signal(signal.SIGINT, self._signal_handler)
        signal.signal(signal.SIGTERM, self._signal_handler)
    
    def _signal_handler(self, signum, frame):
        """Handle shutdown signals gracefully."""
        self.printer.print_warning("\nReceived shutdown signal. Cleaning up...")
        self.is_running = False
        sys.exit(0)
    
    def create_parser(self) -> argparse.ArgumentParser:
        """Create the main argument parser."""
        parser = argparse.ArgumentParser(
            prog='codemcp',
            description='CodeMCP - Universal Function Call Tree Analysis Framework',
            formatter_class=argparse.RawDescriptionHelpFormatter,
            epilog="""
Examples:
  codemcp analyze --file main.py --function main
  codemcp explore --file src/app.py --function process_data --mode manual
  codemcp discover --path /path/to/project --language python
  codemcp classify --file main.py --show-local-only
  codemcp resolve --show-circular --export-graph deps.json
  codemcp config --show
  codemcp session --save my_session
            """.strip()
        )
        
        # Global options
        parser.add_argument(
            '--config', '-c',
            type=str,
            help='Path to configuration file'
        )
        parser.add_argument(
            '--verbose', '-v',
            action='count',
            default=0,
            help='Increase verbosity (use -v, -vv, or -vvv)'
        )
        parser.add_argument(
            '--quiet', '-q',
            action='store_true',
            help='Suppress output except errors'
        )
        parser.add_argument(
            '--output-format',
            choices=['text', 'json', 'yaml', 'table'],
            default='text',
            help='Output format (default: text)'
        )
        parser.add_argument(
            '--no-color',
            action='store_true',
            help='Disable colored output'
        )
        parser.add_argument(
            '--version',
            action='version',
            version='CodeMCP 1.0.0'
        )
        
        # Create subparsers for commands
        subparsers = parser.add_subparsers(
            dest='command',
            help='Available commands',
            metavar='COMMAND'
        )
        
        # Add command parsers
        for command_name, command in self.commands.items():
            command.add_parser(subparsers)
        
        return parser
    
    async def run(self, args: List[str] = None) -> int:
        """Run the CLI application."""
        try:
            # Parse arguments
            parser = self.create_parser()
            parsed_args = parser.parse_args(args)
            
            # Setup configuration
            await self._setup_config(parsed_args)
            
            # Setup output formatting
            self._setup_output(parsed_args)
            
            # Show help if no command specified
            if not parsed_args.command:
                parser.print_help()
                return 0
            
            # Execute command
            command = self.commands[parsed_args.command]
            return await command.execute(parsed_args)
            
        except KeyboardInterrupt:
            self.printer.print_warning("\nOperation cancelled by user")
            return 1
        except CodeMCPError as e:
            error_data = e.to_dict()
            self.printer.print_error(f"CodeMCP Error: {error_data['message']}")
            if parsed_args.verbose > 0:
                self.formatter.print_error_details(error_data)
            return 1
        except Exception as e:
            error_response = handle_error(e, {"command": parsed_args.command if 'parsed_args' in locals() else "unknown"})
            self.printer.print_error(f"Unexpected error: {error_response['message']}")
            if 'parsed_args' in locals() and parsed_args.verbose > 0:
                self.formatter.print_error_details(error_response)
            return 1
    
    async def _setup_config(self, args: argparse.Namespace):
        """Setup configuration from file and arguments."""
        # Load configuration file if specified
        if args.config:
            config_path = Path(args.config)
            if not config_path.exists():
                raise CodeMCPError(f"Configuration file not found: {config_path}")
            self.config = load_config(config_path)
            log_info(f"Loaded configuration from {config_path}")
        else:
            # Try to find default config files
            default_configs = [
                Path.cwd() / "codemcp.toml",
                Path.cwd() / ".codemcp.toml", 
                Path.home() / ".config" / "codemcp" / "config.toml",
                Path.home() / ".codemcp.toml"
            ]
            
            for config_path in default_configs:
                if config_path.exists():
                    self.config = load_config(config_path)
                    log_info(f"Loaded configuration from {config_path}")
                    break
            else:
                # Use default configuration
                self.config = load_config()
        
        # Apply command-line overrides
        if hasattr(args, 'verbose') and args.verbose:
            if args.verbose == 1:
                self.config.logging.level = "INFO"
            elif args.verbose == 2:
                self.config.logging.level = "DEBUG"
            elif args.verbose >= 3:
                self.config.logging.level = "DEBUG"
                # Enable additional debug features
                self.config.debug = True
    
    def _setup_output(self, args: argparse.Namespace):
        """Setup output formatting based on arguments."""
        # Set output format
        if hasattr(args, 'output_format'):
            format_map = {
                'text': OutputFormat.TEXT,
                'json': OutputFormat.JSON,
                'yaml': OutputFormat.YAML,
                'table': OutputFormat.TABLE
            }
            self.formatter.set_format(format_map[args.output_format])
        
        # Configure colors
        if hasattr(args, 'no_color') and args.no_color:
            self.printer.disable_colors()
        
        # Configure quiet mode
        if hasattr(args, 'quiet') and args.quiet:
            self.printer.set_quiet_mode(True)
    
    def print_banner(self):
        """Print the CodeMCP banner."""
        banner = """
╔═══════════════════════════════════════════════════════════════╗
║                            CodeMCP                            ║
║            Universal Function Call Tree Analysis              ║
║                         Framework                             ║
╚═══════════════════════════════════════════════════════════════╝
        """
        self.printer.print_info(banner.strip())
    
    def print_version_info(self):
        """Print version and system information."""
        import platform
        import sys
        
        info = {
            "CodeMCP Version": "1.0.0",
            "Python Version": f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
            "Platform": platform.platform(),
            "Architecture": platform.architecture()[0]
        }
        
        self.formatter.print_key_value_pairs(info)




def main() -> int:
    """Main entry point for the CLI."""
    try:
        # Create and run CLI
        cli = CodeMCPCLI()
        return asyncio.run(cli.run())
    except KeyboardInterrupt:
        print("\nOperation cancelled by user")
        return 1
    except Exception as e:
        print(f"Fatal error: {e}")
        return 1


if __name__ == "__main__":
    sys.exit(main())